package pathfind;

import java.awt.Polygon;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author sad
 */
public class RectRecalculator {

    public RectRecalculator() {
    }

   /* public void formatPolygonGrid(Polygon p) {
        Rectangle2D bounds = p.getBounds2D();
        double minx = bounds.getMinX();
        double maxx = bounds.getMaxX();
        double miny = bounds.getMinY();
        double maxy = bounds.getMaxY();
        minx = ((int) (minx / PolyCell.GRID_SIZE)) * PolyCell.GRID_SIZE;
        maxx = ((int) (maxx / PolyCell.GRID_SIZE) + 1) * PolyCell.GRID_SIZE;
        miny = ((int) (miny / PolyCell.GRID_SIZE)) * PolyCell.GRID_SIZE;
        maxy = ((int) (maxy / PolyCell.GRID_SIZE) + 1) * PolyCell.GRID_SIZE;
        int linesCount = (int) Math.round((maxy - miny) / PolyCell.GRID_SIZE);
        List<PolyCell> intersectionPoints = new ArrayList<>(20);
        List<PolyCell> lastPointLine = null;
        List<PolyCell> fullSquaresList = new ArrayList<>(2000);
        List<PolyCell> lastSquaresLine = null;
        for (int j = 0; j < linesCount; j++) {
            List<PolyCell> currentPointLine = new ArrayList<>(100);
            double y = miny + (j * PolyCell.GRID_SIZE);
            intersectionPoints.clear();
            fillIntersectionPoints(p, minx, y, maxx, y, intersectionPoints);
            int pointCount = intersectionPoints.size();
            for (int i = 0; i < pointCount - 1; i += 2) {
                PolyCell p1 = intersectionPoints.get(i);
                PolyCell p2 = intersectionPoints.get(i + 1);
                List<PolyCell> points = getPointsBetweenTwoOnLine(p1.getX(), p2.getX(), p1.getY(), PolyCell.GRID_SIZE);
                currentPointLine.addAll(points);
            }

            List<PolyCell> sqrs = formatSquares(lastPointLine, currentPointLine);
            if (sqrs != null) {
                fullSquaresList.addAll(sqrs);
            }

            lastPointLine = currentPointLine;
            connectSquaresPairs(lastSquaresLine, sqrs);
            lastSquaresLine = sqrs;
        }

        sortSquaresList(fullSquaresList);
        return fullSquaresList;
    }

    private void sortSquaresList(List<PolyCell> squares) {
        Collections.sort(squares, new Comparator<PolyCell>() {
            @Override
            public int compare(PolyCell o1, PolyCell o2) {
                double delta = o1.getX() - o2.getX();
                if (delta < 0) {
                    return -1;
                }

                if (delta > 0) {
                    return 1;
                }

                return 0;

            }
        });
    }

    private List<PolyCell> formatSquares(List<PolyCell> lastPointLine, List<PolyCell> currentPointLine) {
        if ((lastPointLine == null || lastPointLine.isEmpty()) || (currentPointLine == null || currentPointLine.isEmpty())) {
            return null;
        }

        List<PolyCell> a = lastPointLine;
        List<PolyCell> b = currentPointLine;

        int maxa = a.size() - 1;
        int maxb = b.size() - 1;

        int ai = 0;
        int bi = 0;
        boolean lastgood = false;
        double lastxa = 0, lastya = 0;
        boolean endA = false;
        boolean endB = false;
        List<PolyCell> squares = new ArrayList<>(300);//squares with coordinates in left upper corner and length of edge - grid_size
        PolyCell lastCell = null;
        while (endA == false && endB == false) {
            double xa = a.get(ai).getX();
            double xb = b.get(bi).getX();
            double delta = Math.abs(xa - xb);
            if (delta < 0.0000001) {
                if (lastgood) {
                    double edgeLength = Math.abs(lastxa - xa);
                    if (Math.abs(edgeLength - PolyCell.GRID_SIZE) <= 0.00001) {
                        PolyCell cell = new PolyCell(lastxa, lastya);
                        squares.add(cell);
                        if (lastCell != null) {
                            cell.addConnectedCells(lastCell);
                            lastCell.addConnectedCells(cell);

                        }

                        lastCell = cell;
                    } else {
                        lastCell = null;
                    }
                } else {
                    lastCell = null;
                }

                lastgood = true;
                lastxa = xa;
                lastya = a.get(ai).getY();
                ai++;
                bi++;

                if (ai > maxa) {
                    ai = maxa;
                    endA = true;
                }
                if (bi > maxb) {
                    bi = maxb;
                    endB = true;
                }
            } else {
                lastgood = false;
                if (xa < xb) {
                    ai++;
                    if (ai > maxa) {
                        ai = maxa;
                        endA = true;
                    }
                } else {
                    bi++;
                    if (bi > maxb) {
                        bi = maxb;
                        endB = true;
                    }
                }
            }
        }

        return squares;
    }

    private void connectSquaresPairs(List<PolyCell> lastSquaresLine, List<PolyCell> currentSquaresLine) {
        if ((lastSquaresLine == null || lastSquaresLine.isEmpty()) || (currentSquaresLine == null || currentSquaresLine.isEmpty())) {
            return;
        }

        List<PolyCell> a = lastSquaresLine;
        List<PolyCell> b = currentSquaresLine;

        int maxa = a.size() - 1;
        int maxb = b.size() - 1;

        int ai = 0;
        int bi = 0;
        boolean endA = false;
        boolean endB = false;
        while (endA == false && endB == false) {
            double xa = a.get(ai).getX();
            double xb = b.get(bi).getX();
            double delta = Math.abs(xa - xb);
            if (delta < 0.0000001) {
                a.get(ai).addConnectedCells(b.get(bi));
                b.get(bi).addConnectedCells(a.get(ai));
                ai++;
                bi++;
                if (ai > maxa) {
                    ai = maxa;
                    endA = true;
                }

                if (bi > maxb) {
                    bi = maxb;
                    endB = true;
                }
            } else {
                if (xa < xb) {
                    ai++;
                    if (ai > maxa) {
                        ai = maxa;
                        endA = true;
                    }
                } else {
                    bi++;
                    if (bi > maxb) {
                        bi = maxb;
                        endB = true;
                    }
                }
            }
        }
    }

    private List<PolyCell> getPointsBetweenTwoOnLine(double x1, double x2, double y, double step) {
        List<PolyCell> points = new ArrayList<>(100);
        double x = ((int) (x1 / step) + 1) * step;
        while (x < x2) {
            points.add(new PolyCell(x, y));
            x += step;
        }

        return points;
    }

    private void fillIntersectionPoints(Polygon p, double lx1, double ly1, double lx2, double ly2, List<PolyCell> intersectionPoints) {
        for (int i = 0; i < p.npoints; i++) {
            int x1, x2, y1, y2;
            x1 = p.xpoints[i];
            y1 = p.ypoints[i];
            int secondIndex = i + 1;
            if (secondIndex >= p.npoints) {
                secondIndex = 0;
            }

            x2 = p.xpoints[secondIndex];
            y2 = p.ypoints[secondIndex];

            PolyCell point = Utils.getLineLineIntersection(x1, y1, x2, y2, lx1, ly1, lx2, ly2);
            if (point != null) {
                int index = i;
                if (point.getX() == x1 && point.getY() == y1) {
                    index = i;
                } else if (point.getX() == x2 && point.getY() == y2) {
                    index = secondIndex;
                }

                point.setIndex(index);
                intersectionPoints.add(point);
            }
        }

        fPointXSort(intersectionPoints);
        fixConflictInVertex(intersectionPoints, p);
    }*/

    /**
     * At the vertex we have two intersections.
     * But we should remove only intersection when lines ara lay in different halfplanes
     */
    /*private void fixConflictInVertex(List<PolyCell> points, Polygon p) {
        int iterations = points.size() - 1;
        for (int i = 0; i < iterations; i++) {
            PolyCell p1 = points.get(i);
            PolyCell p2 = points.get(i + 1);
            if (p1.getIndex() > p2.getIndex()) {
                PolyCell t = p2;
                p2 = p1;
                p1 = t;
            }

            if (p1.equals(p2)) {
                double y1 = p.ypoints[ensureLinkedPointIndex(p1.getIndex() - 1, p.npoints)];
                double y2 = p.ypoints[ensureLinkedPointIndex(p2.getIndex() + 1, p.npoints)];
                double y = p1.getY();
                boolean shouldremove = true;
                if (y1 < y) {
                    if (y2 < y) {
                        shouldremove = false;
                    }
                }

                if (y1 > y) {
                    if (y2 > y) {
                        shouldremove = false;
                    }
                }

                if (shouldremove) {
                    points.remove(i);
                    i--;
                    iterations--;
                }
            }
        }
    }

    private void fPointXSort(List<PolyCell> intersectionPoints) {
        Collections.sort(intersectionPoints, new Comparator<PolyCell>() {
            @Override
            public int compare(PolyCell o1, PolyCell o2) {
                if (o1.getX() < o2.getX()) {
                    return -1;
                }

                if (o1.getX() == o2.getX()) {
                    return 0;
                }

                if (o1.getX() > o2.getX()) {
                    return 1;
                }

                return 1;
            }
        });
    }

    private int ensureLinkedPointIndex(int currentIndex, int totalSize) {
        if (currentIndex >= totalSize) {
            return 0;
        }

        if (currentIndex < 0) {
            return totalSize - 1;
        }

        return currentIndex;
    }*/
}
